﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Shell;
using XamlingCore.Infrastructure.Navigation;
using XamlingCore.Infrastructure.Serialisation;
using XamlingCore.Infrastructure.Tombstone;
using XamlingCore.Infrastructure.View;
using XamlingCore.WP.Infrastructure.View.Interface;

namespace XamlingCore.WP.Infrastructure.Lifetime
{
    public class Bootstrapper<T>
        where T :  XFrameViewModelBase, new()
    {
        private PhoneApplicationService service;

        private XFrameViewModelBase rootFrameModel;

        private const string TombstoneKey = "Tombstone";
        private const string TombstoneTypesKey = "TombstoneTypes";

        public bool Resumed { get; set; }

        public Bootstrapper(PhoneApplicationService service)
        {
            this.service = service;

            service.Deactivated += service_Deactivated;
        }

        public bool BackKeyPressed()
        {
            if (rootFrameModel.NavigationService.CanGoBack)
            {
                rootFrameModel.NavigateBack();
                return true;
            }
            else
            {
                return false;
            }
        }

        public T CreateRootFrameModel()
        {
            var newModel = XFrameViewModelBase.CreateRootFrame<T>();
            rootFrameModel = newModel;
            return newModel;
        }

        public T RestoreOrCreateRootFrameModel()
        {
            if (PhoneApplicationService.Current.State.ContainsKey(TombstoneKey) && PhoneApplicationService.Current.State.ContainsKey(TombstoneTypesKey))
            {
                Debug.WriteLine("De-Tombstone Start");
                var ser = PhoneApplicationService.Current.State[TombstoneKey] as string;
                Debug.WriteLine("Tomdsone content length: {0}", ser.Length);
                var typesString = PhoneApplicationService.Current.State[TombstoneTypesKey] as List<string>;

                var types = new List<Type>();

                foreach (var item in typesString)
                {
                    var type = Type.GetType(item);
                    types.Add(type);
                }

                var newModel = Serialise.DeSerialiseEntity<T>(ser, types);

                XFrameViewModelBase.RootFrame = newModel;

                rootFrameModel = newModel;
                rootFrameModel.KnownTypes = new List<Type>();
                rootFrameModel.KnownTypes.Add(typeof(T));
                rootFrameModel.NavigationService.ParentFrame = rootFrameModel;
                rootFrameModel.IsReactivated = true;
                rootFrameModel.OnReactivate(()=>
                                                {
                                                    foreach (var item in rootFrameModel.NavigationService.NavigationHistory)
                                                    {
                                                        var itemType = item.GetType();
                                                        if (!rootFrameModel.KnownTypes.Contains(itemType))
                                                        {
                                                            rootFrameModel.KnownTypes.Add(itemType);
                                                        }
                                                        
                                                        var contentModel = item as XContentViewModelBase;
                                                        if (contentModel != null)
                                                        {
                                                            contentModel.ParentModel =
                                                                rootFrameModel.FindModel(contentModel.ParentModelGuid);
                                                            
                                                            contentModel.IsReady = true;
                                                        }


                                                        var resume = item as IReactivate;
                                                        
                                                        if (resume != null)
                                                        {
                                                            resume.OnReactivate();
                                                        }
                                                    }
                                                    if (rootFrameModel.NavigationService.SerialiseContentObject != null)
                                                    {
                                                        var type =
                                                            rootFrameModel.NavigationService.SerialiseContentObject.
                                                                GetType();
                                                        if (!rootFrameModel.KnownTypes.Contains(type))
                                                        {
                                                            rootFrameModel.KnownTypes.Add(type);
                                                        }
                                                        
                                                    }
                                                    rootFrameModel.NavigationService.Resume();
                                                    Debug.WriteLine("De-Tombstone End");
                                                });
                
                return newModel;
            }
            else
            {
                return CreateRootFrameModel();
            }
        }

        private void Tombstone()
        {
            var ser = RootFrameModel.Serialise();

            if (PhoneApplicationService.Current.State.ContainsKey(TombstoneKey))
            {
                PhoneApplicationService.Current.State.Remove(TombstoneKey);
            }

            PhoneApplicationService.Current.State.Add(TombstoneKey, ser);

            List<string> types = new List<string>();
            
            foreach (var item in RootFrameModel.KnownTypes)
            {
                if (!types.Contains(item.AssemblyQualifiedName))
                {
                    types.Add(item.AssemblyQualifiedName);    
                }
            }

            if (PhoneApplicationService.Current.State.ContainsKey(TombstoneTypesKey))
            {
                PhoneApplicationService.Current.State.Remove(TombstoneTypesKey);
            }

            PhoneApplicationService.Current.State.Add(TombstoneTypesKey, types);
            
        }

        public XFrameViewModelBase RootFrameModel
        {
            get
            {
                if(rootFrameModel == null)
                {
                    throw new Exception("Cannot call RootFrameModel before ");
                }
                return rootFrameModel;
            }
        }

        void service_Deactivated(object sender, DeactivatedEventArgs e)
        {
            Tombstone();
        }

        
    }
}
